package com.tbit.uqbike.service.business.impl;

import com.alibaba.fastjson.JSON;
import com.github.pagehelper.PageHelper;
import com.tbit.uqbike.annos.EncapsulateMap;
import com.tbit.uqbike.constant.Constants;
import com.tbit.uqbike.constant.RedisConstant;
import com.tbit.uqbike.constant.WorkType;
import com.tbit.uqbike.object.pojo.AccountUser;
import com.tbit.common.entity.pojo.vo.DateResult;
import com.tbit.uqbike.object.pojo.PowerChangeRedis;
import com.tbit.uqbike.object.pojo.statistics.ExportPowerLog;
import com.tbit.uqbike.object.pojo.statistics.MoveLog;
import com.tbit.uqbike.service.base.RedisService;
import com.tbit.uqbike.service.business.AccountUserService;
import com.tbit.uqbike.service.business.MoveLogService;
import com.tbit.uqbike.webmanager.dao.core.WorkOrderDao;
import com.tbit.uqbike.webmanager.dao.log.MoveLogDao;
import com.tbit.uqbike.webmanager.util.StringUtils;
import com.tbit.utils.DateTimeUtil;
import com.tbit.utils.NullUtils;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.collections.MapUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.serializer.SerializationException;
import org.springframework.stereotype.Service;

import java.text.SimpleDateFormat;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * @Author: chen
 * @Description: 挪车记录
 * @Date: 创建于 17:36 2020/3/13
 */
@Service("/moveLogService")
public class MoveLogServiceImpl implements MoveLogService {
    @Autowired
    private MoveLogDao moveLogDao;
    @Autowired
    private AccountUserService accountUserService;
    @Autowired
    private RedisService redisService;

    @Override
    public List<DateResult> statisticsByTime(Integer accountId, Integer accountUserId, Long startTime,
                                             Long endTime) {
        Map<String, Object> map = new HashMap<>();
        map.put("accountId", accountId);
        map.put("accountUserId", accountUserId);
        map.put("startTime", new Date(startTime));
        map.put("endTime", new Date(endTime));
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");

        /**获取传入时间每天的日期*/
        List<String> findTimeList = DateTimeUtil.findDaysStr(simpleDateFormat.format(new Date(startTime)), simpleDateFormat.format(new Date(endTime)));
        /**获取要查询的数据*/
        List<DateResult> results = moveLogDao.statisticsByTime(map);
        /**获取查询数据的日期集合*/
        List<String> dateList = results.stream().map(DateResult::getDate).collect(Collectors.toList());
        /**得到传入时间和查询数据日期集合的差集*/
        List<String> reduce = findTimeList.stream().filter(item -> !dateList.contains(item)).collect(Collectors.toList());
        /**进行补0*/
        if (!NullUtils.isEmpty(reduce)) {
            for (String date : reduce) {
                DateResult dateResult = new DateResult();
                dateResult.setDate(date);
                dateResult.setTotal(0);
                results.add(dateResult);
            }
        }
        /**根据日期排序*/
        results = results.stream().sorted(Comparator.comparing(DateResult::getDate)).collect(Collectors.toList());


        return results;
    }

    @Override
    public List<MoveLog> queryPage(Integer accountId, String machineNO, String userCode,
                                   Integer accountUserId, Long startTime, Long endTime, Integer pageNO, Integer rowCount) {
        Map<String, Object> map = new HashMap<>();
        map.put("accountId", accountId);
        map.put("machineNO", machineNO);
        map.put("userCode", userCode);
        map.put("accountUserId", accountUserId);
        map.put("startTime", new Date(startTime));
        map.put("endTime", new Date(endTime));
        map.put("pageNO", (pageNO - 1) * rowCount);
        map.put("rowCount", rowCount);
        List<MoveLog> logs = moveLogDao.queryPage(map);
        if (CollectionUtils.isEmpty(logs)){
            return logs;
        }
        Map<String, String> machineMoveMap = redisService.getAll(RedisConstant.REDIS_TER_BIKE_MOVE_CHANGE_RIDE_MAP);
        Set<Integer> accountUserIdList = logs.stream().map(MoveLog::getAccountUserId).filter(Objects::nonNull).collect(Collectors.toSet());
        if (CollectionUtils.isEmpty(accountUserIdList)){
            logs.forEach(moveLog -> {
                //审核中状态只有在挪车所有条件都生效，并且需要校验是否产生订单时
                this.checkMoveLogIsValid(moveLog,machineMoveMap);
            });
            return logs;
        }
        List<AccountUser> list = accountUserService.getAccountUserByIds(accountUserIdList);
        if (CollectionUtils.isEmpty(list)){
            return logs;
        }
        Map<Integer, AccountUser> accountUserMap = list.stream().collect(Collectors.toMap(AccountUser::getAccountUserId, Function.identity()));
        logs.forEach(moveLog -> {
            AccountUser accountUser = accountUserMap.get(moveLog.getAccountUserId());
            if (Objects.nonNull(accountUser)){
                moveLog.setName(accountUser.getName());
                moveLog.setPhone(accountUser.getPhone());
            }
            //审核中状态只有在挪车所有条件都生效，并且需要校验是否产生订单时
            this.checkMoveLogIsValid(moveLog,machineMoveMap);

        });
        return logs;
    }

    @Override
    public Integer queryCount(Integer accountId, String machineNO, String userCode,
                              Integer accountUserId, Long startTime, Long endTime) {
        Map<String, Object> map = new HashMap<>();
        map.put("accountId", accountId);
        map.put("userCode", userCode);
        map.put("machineNO", machineNO);
        map.put("accountUserId", accountUserId);
        map.put("startTime", new Date(startTime));
        map.put("endTime", new Date(endTime));
        return moveLogDao.queryCount(map);
    }

    @Override
    public List<MoveLog> exportByTime(Integer accountId, Integer accountUserId, Long startTime,
                                      Long endTime) {
        Map<String, Object> map = new HashMap<>();
        map.put("startTime", new Date(startTime));
        map.put("accountId", accountId);
        map.put("endTime", new Date(endTime));
        map.put("accountUserId", accountUserId);
        List<MoveLog> logs = moveLogDao.exportByTime(map);
        List<AccountUser> list = accountUserService.getByType(accountId, false);
        if (list.size() > 0) {
            /**填充运维人员数据*/
            for (AccountUser a : list) {
                for (MoveLog e : logs) {
                    if (a.getAccountUserId().equals(e.getAccountUserId())) {
                        e.setName(a.getName());
                        e.setPhone(a.getPhone());
                    }
                }
            }
        }

        return logs;
    }

    @Override
    @EncapsulateMap
    public List<ExportPowerLog> getByType(Map<String, Object> params, Integer accountId, Integer accountUserId, Long startTime, Long endTime, Integer rowCount, Integer pageNO) {
        PageHelper.startPage(pageNO, rowCount);
        List<ExportPowerLog> logs = moveLogDao.selectByType(params);
        List<AccountUser> list = accountUserService.getByType(accountId, false);
        if (list.size() > 0) {
            /**填充运维人员数据*/
            for (AccountUser a : list) {
                for (ExportPowerLog e : logs) {
                    if (a.getAccountUserId().equals(e.getAccountUserId())) {
                        e.setName(a.getName());
                        e.setPhone(a.getPhone());
                    }
                }
            }
        }
        return logs;
    }

    /**
     * @description: 检查挪车记录是否在审核中
     * @author: mo.shanyong
     * @date: 2025/5/19 20:06
     * @param: moveLog
     * @param: machineMoveMap
     */
    private void checkMoveLogIsValid(MoveLog moveLog,Map<String, String> machineMoveMap){
        if (MapUtils.isNotEmpty(machineMoveMap) &&
                Objects.equals(moveLog.getIsValid(), Constants.VALID) && machineMoveMap.containsKey(moveLog.getMachineNO())){
            //如果车辆的挪车记录有在审核中的，要判断是否是当前挪车记录，一辆车会有多个挪车记录
            String powerChangeRedisListStr = redisService.get(RedisConstant.REDIS_TER_MOVE_CHANGE_RIDE + moveLog.getMachineNO());
            if (StringUtils.isBlank(powerChangeRedisListStr)){
                redisService.hdel(RedisConstant.REDIS_TER_BIKE_MOVE_CHANGE_RIDE_MAP, moveLog.getMachineNO());
                return;
            }
            List<PowerChangeRedis> powerChangeRedisList = new LinkedList<>();
            try {
                powerChangeRedisList = JSON.parseArray(powerChangeRedisListStr, PowerChangeRedis.class);
            } catch (SerializationException e) {
                redisService.del(RedisConstant.REDIS_TER_MOVE_CHANGE_RIDE + moveLog.getMachineNO());
            }
            PowerChangeRedis powerChangeRedis = powerChangeRedisList.stream().filter(p -> {
                return Objects.equals(moveLog.getMoveLogId(), p.getPowerChangeId());
            }).findFirst().orElse(null);
            //如果当前挪车记录存在挪车订单缓存数据，则判定当前挪车记录是在审核中
            moveLog.setIsValid(Objects.nonNull(powerChangeRedis) ? WorkType.workOrder_state_audit : moveLog.getIsValid());
        }
    }
}
